<template>
  <view class="b-waterfall">
    <view id="u-left-column" class="b-column">
      <view v-for="(item, index) in leftList">
        <slot name="waterfallItem1" v-bind:item="item"></slot>
      </view>
    </view>
    <view id="u-right-column" class="b-column">
      <view v-for="(item, index) in rightList">
        <slot name="waterfallItem2" v-bind:item="item"></slot>
      </view>
    </view>
  </view>
</template>

<script>
  export default {
    name: "b-waterfall",
    props: {
      dataSource: {
        // 瀑布流数据
        type: Array,
        required: true,
        default: function () {
          return [];
        }
      },
      // 每次向结构插入数据的时间间隔，间隔越长，越能保证两列高度相近，但是对用户体验越不好
      // 单位ms
      addTime: {
        type: [Number, String],
        default: 0
      },
      onLoadMore: {
        type: Promise
      }
    },
    data() {
      return {
        leftList: [],
        rightList: [],
        tempList: this.dataSource
      }
    },
    mounted() {
      this.tempList = this.cloneData(this.dataSource);
      this.splitData(this.tempList);
    },
    methods: {
      getRect(selector, all) {
        return new Promise(resolve => {
          uni.createSelectorQuery().in(this)[all ? 'selectAll' : 'select'](selector)
            .boundingClientRect(rect => {
              if (all && Array.isArray(rect) && rect.length) {
                resolve(rect)
              }
              if (!all && rect) {
                resolve(rect)
              }
            })
            .exec()
        })
      },
      async splitData() {
        if (this.tempList.length == 0) return;
        let leftRect = await this.getRect('#u-left-column');
        let rightRect = await this.getRect('#u-right-column');
        // 如果左边小于或等于右边，就添加到左边，否则添加到右边
        let item = this.tempList.shift();
        // 解决多次快速上拉后，可能数据会乱的问题，因为经过上面的两个await节点查询阻塞一定时间，加上后面的定时器干扰
        // 数组可能变成[]，导致此item值可能为undefined
        if (!item) return;
        if (leftRect.height <= rightRect.height) {
          this.leftList.push(item);
        } else {
          this.rightList.push(item);
        }
        // 如果临时数组还有数据，继续循环
        if (this.tempList.length > 0) {
          setTimeout(() => {
            this.splitData();
          }, this.addTime)
        } else {
        }
      },
      // 复制而不是引用对象和数组
      cloneData(data) {
        return data.concat([]);
      },
      /**
       * 追加的数据
       * @param data
       */
      addItems(data) {
        this.tempList = data
        this.splitData()
      }
    }
  }
</script>

<style scoped>

  .b-waterfall {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
  }

  .b-column {
    display: flex;
    flex: 1;
    flex-direction: column;
    height: auto;
  }

</style>
